﻿using System;
using System.Windows.Forms;
using System.Drawing;

namespace TutorialDoubleBuffering
{
	public class Application
	{
		private Form mainWnd = null;

		private BufferedGraphicsContext context = null;
		private BufferedGraphics grafx = null;

		private Game game = null;

		public Application(Game game)
		{
			this.game = game;
			this.game.App = this;
			this.game.MainWnd = this.mainWnd;
		}

		public bool Run()
		{
			if (!Init())
				return false;

			RunGameLoop();

			return true;
		}

		private bool Init()
		{
			CreateWindow();
			CreateGraphics();

			return this.game.Init();
		}

		private void CreateWindow()
		{
			this.mainWnd = new Form();
			this.mainWnd.ClientSize = new Size(640, 480);
			this.mainWnd.Text = "My Testris";
			this.mainWnd.MaximizeBox = false;
			this.mainWnd.FormBorderStyle = FormBorderStyle.FixedSingle;

			this.mainWnd.Show();
		}

		private void CreateGraphics()
		{
			this.context = BufferedGraphicsManager.Current;
			this.context.MaximumBuffer
				= new Size(this.mainWnd.ClientRectangle.Width, this.mainWnd.ClientRectangle.Height);
			this.grafx = this.context.Allocate(this.mainWnd.CreateGraphics(), this.mainWnd.ClientRectangle);
		}

		private void RunGameLoop()
		{
			int elapsedTime = 0;
			int beforeTime = Environment.TickCount;

			while (mainWnd.Created)
			{
				System.Threading.Thread.Sleep(1);

				elapsedTime = Environment.TickCount - beforeTime;
				if (elapsedTime > 1)
				{
					this.Input(elapsedTime);
					this.UpdateFrame(elapsedTime);
					this.RenderFrame(elapsedTime);

					beforeTime = Environment.TickCount;
				}

				System.Windows.Forms.Application.DoEvents();
			}
		}

		private void Input(int elapsedTime)
		{
			this.game.Input(elapsedTime);
		}

		private void UpdateFrame(int elapsedTime)
		{
			this.game.UpdateFrame(elapsedTime);
		}

		private void RenderFrame(int elapsedTime)
		{
			this.grafx.Graphics.FillRectangle(Brushes.Gray, 0, 0,
				this.context.MaximumBuffer.Width, this.context.MaximumBuffer.Height);

			this.game.RenderFrame(this.grafx.Graphics, elapsedTime);

			this.grafx.Render();
		}
	}
}
